﻿namespace Jermaine.UI
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Windows.Forms;


    [Flags]
    public enum KeyModifiers
    {
        None = 0,
        Alt = 1,
        Ctrl = 2,
        Shift = 4,
        WindowsKey = 8
    }

    public class SmartConsole
    {

        private SmartConsole() { }

        public static void Initialize() {
            console = new ConsoleForm();
        }

        private static ConsoleForm console;

        public static void Write(String message, MessageType messageType = MessageType.Normal) {
            console.Append(message, messageType);
        }

        #region Console Form
        private class ConsoleForm : Form
        {
            private Dictionary<MessageType, Color> colors = new Dictionary<MessageType, Color>();
            private const int HOT_KEY_CODE = 0x1010;

            public ConsoleForm() {
                InitializeComponent();

                NativeMethods.RegisterHotKey(Handle, HOT_KEY_CODE,
                    (uint)(KeyModifiers.Ctrl | KeyModifiers.Shift),
                    (uint)Keys.C);

                colors.Add(MessageType.Normal, Color.White);
                colors.Add(MessageType.Warn, Color.YellowGreen);
                colors.Add(MessageType.Error, Color.Red);
                this.ShowIcon = false;
            }

            protected override void WndProc(ref Message m) {
                const int WM_HOTKEY = 0x0312;
                switch (m.Msg) {
                    case WM_HOTKEY:
                        switch (m.WParam.ToInt32()) {
                            case HOT_KEY_CODE:
                                if (this.Visible) {
                                    this.Hide();
                                } else {
                                    this.Show();
                                }
                                break;
                        }
                        break;
                }
                base.WndProc(ref m);
            }

            protected override void OnClosing(CancelEventArgs e) {
                this.Hide();
                e.Cancel = true;
                base.OnClosing(e);
            }

            private System.ComponentModel.IContainer components = null;

            protected override void Dispose(bool disposing) {
                if (disposing && (components != null)) {
                    components.Dispose();
                }

                if (disposing && (this.font != null)) {
                    this.font.Dispose();
                }

                NativeMethods.UnregisterHotKey(Handle, HOT_KEY_CODE);
                base.Dispose(disposing);

            }

            #region Windows Form Designer generated code

            private void InitializeComponent() {
                this.txtInfoArea = new System.Windows.Forms.RichTextBox();
                this.SuspendLayout();
                // 
                // txtInfoArea
                // 
                this.txtInfoArea.BackColor = System.Drawing.SystemColors.WindowText;
                this.txtInfoArea.BorderStyle = System.Windows.Forms.BorderStyle.None;
                this.txtInfoArea.Dock = System.Windows.Forms.DockStyle.Fill;
                this.txtInfoArea.Font = new System.Drawing.Font("Consolas", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                this.txtInfoArea.ForeColor = System.Drawing.SystemColors.Window;
                this.txtInfoArea.Location = new System.Drawing.Point(0, 0);
                this.txtInfoArea.Multiline = true;
                this.txtInfoArea.Name = "txtInfoArea";
                this.txtInfoArea.ReadOnly = true;
                this.txtInfoArea.ScrollBars = RichTextBoxScrollBars.Vertical;
                this.txtInfoArea.Size = new System.Drawing.Size(550, 390);
                this.txtInfoArea.TabIndex = 0;
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(550, 390);
                this.Controls.Add(this.txtInfoArea);
                this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
                this.MaximizeBox = false;
                this.Name = "SmartConsole";
                this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
                this.Text = "SmartConsole";
                this.ResumeLayout(false);
                this.PerformLayout();

            }
            #endregion

            #region Fields
            private System.Windows.Forms.RichTextBox txtInfoArea;
            private int currentPosition = 0;
            private Font font = new System.Drawing.Font("Consolas", 10.0F, System.Drawing.FontStyle.Regular,
                System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            #endregion

            internal void Append(string message, MessageType messageType) {

                UIInvoker.AsyncCall<string, MessageType>(this,
                    new Action<string, MessageType>((m, t) => {
                        var color = this.colors[t];
                        m = string.Format("{0} [{1}] {2}", System.DateTime.Now.ToString("HH:mm:ss"),
                            t.ToString().PadRight(5, ' '), m);
                        this.txtInfoArea.AppendText(m + Environment.NewLine);
                        this.txtInfoArea.Select(currentPosition, m.Length);
                        this.txtInfoArea.SelectionFont = font;
                        this.txtInfoArea.SelectionColor = color;
                        this.txtInfoArea.SelectionBackColor = SystemColors.WindowText;
                        currentPosition += (m.Length + 1);
                        this.txtInfoArea.Select(currentPosition, 0);
                    }),
                    message,
                    messageType);


            }
        }
        #endregion

        #region MessageType
        public enum MessageType
        {
            Normal, Warn, Error
        }
        #endregion
    }

}
